package com.example.demo.service;

import com.example.demo.model.Configuration;
import com.example.demo.model.ConfigField;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import org.apache.poi.xssf.usermodel.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;
import org.springframework.transaction.annotation.Transactional;

/**
 * 数据生成服务
 * 负责根据配置生成模拟数据
 */
@Service
@Slf4j
public class DataGeneratorService {
    // 用于生成中文姓名的数据
    private static final String[] FIRST_NAMES = {
        "张", "王", "李", "赵", "刘", "陈", "杨", "黄", "周", "吴",
        "郑", "孙", "马", "朱", "胡", "林", "郭", "何", "高", "罗"
    };
    private static final String[] LAST_NAMES = {
        "伟", "芳", "娜", "秀英", "敏", "静", "丽", "强", "磊", "军",
        "洋", "勇", "艳", "杰", "涛", "明", "超", "秀兰", "霞", "平"
    };

    // 添加城市数据
    private static final String[] CITIES = {
        "北京", "上海", "广州", "深圳", "杭州", 
        "南京", "成都", "武汉", "西安", "重庆"
    };

    private final Random random = new Random();
    private final ObjectMapper objectMapper = new ObjectMapper();
    private static final int BATCH_SIZE = 5000; // 增加批处理大小
    private static final int MAX_THREADS = 16;  // 限制最大线程数
    
    private final ExecutorService executorService = Executors.newFixedThreadPool(
        Math.min(Runtime.getRuntime().availableProcessors() * 2, MAX_THREADS)
    );

    // 缓存常用的随机数据
    private static final List<String> CACHED_UUIDS = IntStream.range(0, 1000)
        .mapToObj(i -> UUID.randomUUID().toString())
        .collect(Collectors.toList());

    // 手机号前缀
    private static final String[] PHONE_PREFIXES = {
            "133", "135", "136", "137", "138", "139",
            "150", "151", "152", "157", "158", "159",
            "182", "183", "187", "188", "189"
    };

    // 邮箱域名
    private static final String[] EMAIL_DOMAINS = {
            "gmail.com", "yahoo.com", "hotmail.com",
            "outlook.com", "163.com", "qq.com"
    };
        
    private static final List<String> CACHED_PHONES = IntStream.range(0, 1000)
        .mapToObj(i -> {
            String prefix = PHONE_PREFIXES[i % PHONE_PREFIXES.length];
            return prefix + String.format("%08d", i);
        })
        .collect(Collectors.toList());
        
    private static final List<String> CACHED_EMAILS = IntStream.range(0, 1000)
        .mapToObj(i -> {
            String name = FIRST_NAMES[i % FIRST_NAMES.length].toLowerCase() + i;
            String domain = EMAIL_DOMAINS[i % EMAIL_DOMAINS.length];
            return name + "@" + domain;
        })
        .collect(Collectors.toList());



    private static final List<String> CACHED_NAMES = IntStream.range(0, 1000)
        .mapToObj(i -> {
            String firstName = FIRST_NAMES[i % FIRST_NAMES.length];
            String lastName = LAST_NAMES[i % LAST_NAMES.length];
            return firstName + lastName;
        })
        .collect(Collectors.toList());

    /**
     * 根据配置生成数据
     * @param config 配置信息
     * @return 生成的数据列表，每条数据是一个Map
     */
    @Transactional(readOnly = true)
    public List<Map<String, String>> generateData(Configuration config) {
        log.info("开始生成数据，配置ID: {}, 数据量: {}", config.getId(), config.getDataCount());
        
        // 预先获取所有需要的数据
        List<ConfigField> fields = new ArrayList<>(config.getFields());
        int totalCount = config.getDataCount() != null ? config.getDataCount() : 10;
        int batchCount = (totalCount + BATCH_SIZE - 1) / BATCH_SIZE;

        try {
            List<CompletableFuture<List<Map<String, String>>>> futures = IntStream.range(0, batchCount)
                .mapToObj(batch -> CompletableFuture.supplyAsync(() -> {
                    int start = batch * BATCH_SIZE;
                    int count = Math.min(BATCH_SIZE, totalCount - start);
                    return generateBatch(fields, count);
                }, executorService))
                .collect(Collectors.toList());

            List<Map<String, String>> result = futures.stream()
                .map(CompletableFuture::join)
                .flatMap(List::stream)
                .collect(Collectors.toList());

            log.info("数据生成完成，共生成 {} 条记录", result.size());
            return result;
        } catch (Exception e) {
            log.error("生成数据时发生错误", e);
            throw e;
        }
    }

    private List<Map<String, String>> generateBatch(List<ConfigField> fields, int count) {
        List<Map<String, String>> batchData = new ArrayList<>(count);
        for (int i = 0; i < count; i++) {
            Map<String, String> rowData = new LinkedHashMap<>();
            for (ConfigField field : fields) {
                rowData.put(field.getFieldName(), generateFieldValue(field));
            }
            batchData.add(rowData);
        }
        return batchData;
    }

    /**
     * 根据字段配置生成单个字段的值
     * @param field 字段配置
     * @return 生成的字段值
     */
    private String generateFieldValue(ConfigField field) {
        String type = field.getFieldType().toLowerCase();
        try {
            switch (type) {
                case "uuid":
                    return CACHED_UUIDS.get(random.nextInt(CACHED_UUIDS.size()));
                case "name":
                    String name = CACHED_NAMES.get(random.nextInt(CACHED_NAMES.size()));
                    if (field.getFormat() != null && field.getFormat().equals("lastName_firstName")) {
                        name = name.substring(1) + name.charAt(0);
                    }
                    return addPrefixSuffix(name, field);
                case "phone":
                    return CACHED_PHONES.get(random.nextInt(CACHED_PHONES.size()));
                case "email":
                    return CACHED_EMAILS.get(random.nextInt(CACHED_EMAILS.size()));
                case "age":
                    return generateAge(field);
                case "date":
                    return generateDate(field);
                case "city":
                    return generateCity();
                case "number":
                    return generateNumber(field);
                case "text":
                    return generateText(field);
                default:
                    log.warn("未知的字段类型: {}", type);
                    return "";
            }
        } catch (Exception e) {
            log.error("生成字段值时发生错误", e);
            return "";
        }
    }

    private String addPrefixSuffix(String value, ConfigField field) {
        return (field.getPrefix() != null ? field.getPrefix() : "") +
               value +
               (field.getSuffix() != null ? field.getSuffix() : "");
    }

    private String generateDate(ConfigField field) {
        LocalDateTime now = LocalDateTime.now();
        String format = field.getFormat();
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd";
        }
        
        // 如果设置了最小值和最大值，随机生成范围内的日期
        if (field.getMinValue() != null && field.getMaxValue() != null) {
            long minDay = now.minusDays(field.getMaxValue()).toLocalDate().toEpochDay();
            long maxDay = now.minusDays(field.getMinValue()).toLocalDate().toEpochDay();
            long randomDay = minDay + random.nextInt((int) (maxDay - minDay));
            LocalDate randomDate = LocalDate.ofEpochDay(randomDay);
            return randomDate.format(DateTimeFormatter.ofPattern(format));
        }
        
        return now.format(DateTimeFormatter.ofPattern(format));
    }

    private String generateCity() {
        return CITIES[random.nextInt(CITIES.length)];
    }

    private String generateNumber(ConfigField field) {
        int min = field.getMinValue() != null ? field.getMinValue() : 0;
        int max = field.getMaxValue() != null ? field.getMaxValue() : 100;
        int number = random.nextInt(max - min + 1) + min;
        
        // 如果有格式化模板，使用String.format
        if (field.getFormat() != null && !field.getFormat().isEmpty()) {
            return String.format(field.getFormat(), number);
        }
        
        return String.valueOf(number);
    }

    private String generateText(ConfigField field) {
        int length = field.getMaxValue() != null ? field.getMaxValue() : 10;
        StringBuilder text = new StringBuilder();
        String chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        
        for (int i = 0; i < length; i++) {
            text.append(chars.charAt(random.nextInt(chars.length())));
        }
        
        return (field.getPrefix() != null ? field.getPrefix() : "") +
               text.toString() +
               (field.getSuffix() != null ? field.getSuffix() : "");
    }

    private String generateAge(ConfigField field) {
        int min = field.getMinValue() != null ? field.getMinValue() : 18;
        int max = field.getMaxValue() != null ? field.getMaxValue() : 60;
        return String.valueOf(random.nextInt(max - min + 1) + min);
    }

    /**
     * 生成Excel文件
     * @param data 要导出的数据
     * @param fields 字段配置列表
     * @return Excel文件的字节数组
     */
    public byte[] generateExcel(List<Map<String, String>> data, List<ConfigField> fields) throws IOException {
        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
            XSSFSheet sheet = workbook.createSheet("Generated Data");
            
            // 创建标题行
            XSSFRow headerRow = sheet.createRow(0);
            for (int i = 0; i < fields.size(); i++) {
                headerRow.createCell(i).setCellValue(fields.get(i).getFieldName());
            }
            
            // 填充数据
            for (int i = 0; i < data.size(); i++) {
                XSSFRow row = sheet.createRow(i + 1);
                Map<String, String> rowData = data.get(i);
                int cellIndex = 0;
                for (ConfigField field : fields) {
                    row.createCell(cellIndex++).setCellValue(rowData.get(field.getFieldName()));
                }
            }
            
            // 自动调整列宽
            for (int i = 0; i < fields.size(); i++) {
                sheet.autoSizeColumn(i);
            }
            
            // 将工作簿写入字节数组
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            workbook.write(outputStream);
            return outputStream.toByteArray();
        }
    }

    /**
     * 生成CSV格式的字节数组
     */
    public byte[] generateCsvBytes(List<Map<String, String>> data, List<ConfigField> fields) throws IOException {
        log.info("开始生成CSV文件，数据量: {}", data.size());
        try {
            StringBuilder csv = new StringBuilder();
            
            // 添加BOM标记，支持Excel打开显示中文
            csv.append('\uFEFF');
            
            // 添加表头
            csv.append("序号,");
            csv.append(fields.stream()
                .map(ConfigField::getFieldName)
                .collect(Collectors.joining(",")));
            csv.append("\n");
            
            // 添加数据行
            for (int i = 0; i < data.size(); i++) {
                csv.append(i + 1).append(",");
                Map<String, String> row = data.get(i);
                csv.append(fields.stream()
                    .map(field -> row.get(field.getFieldName()))
                    .map(this::escapeCsvField)
                    .collect(Collectors.joining(",")));
                csv.append("\n");
            }
            
            byte[] bytes = csv.toString().getBytes(StandardCharsets.UTF_8);
            log.info("CSV文件生成完成，大小: {} bytes", bytes.length);
            return bytes;
        } catch (Exception e) {
            log.error("生成CSV文件时发生错误", e);
            throw e;
        }
    }

    /**
     * 生成JSON格式的字节数组
     */
    public byte[] generateJsonBytes(List<Map<String, String>> data) throws IOException {
        log.info("开始生成JSON文件，数据量: {}", data.size());
        try {
            byte[] bytes = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsBytes(data);
            log.info("JSON文件生成完成，大小: {} bytes", bytes.length);
            return bytes;
        } catch (Exception e) {
            log.error("生成JSON文件时发生错误", e);
            throw e;
        }
    }

    /**
     * CSV字段值转义处理
     */
    private String escapeCsvField(String field) {
        if (field == null) {
            return "";
        }
        if (field.contains(",") || field.contains("\"") || field.contains("\n")) {
            return "\"" + field.replace("\"", "\"\"") + "\"";
        }
        return field;
    }
} 